/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package bea.cliente.character;

import bea.cliente.core.Game;
import com.jme3.animation.AnimControl;
import com.jme3.bounding.BoundingBox;
import com.jme3.bullet.collision.shapes.CapsuleCollisionShape;
import com.jme3.bullet.control.CharacterControl;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Node;

/**
 *
 * @author Ivan
 */
public class Character extends Node {

    // core variables
    public Game game;
    // variaveis do modelo
    private Node model;
    // variaveis da animação
    private CharacterAnimControl animControl;
    // physics
    private CharacterControl chControl;
    // variaveis de controle de movimento
    Vector3f walkDirection = new Vector3f();
    Quaternion modelRotation = new Quaternion();
    Vector3f modelDirection = new Vector3f();
    Vector3f modelRight = new Vector3f();
    public static float DISTANCE_STOP = 0.5f;
    static final Quaternion ROTATE_LEFT = new Quaternion();

    static {
        ROTATE_LEFT.fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_Y);
    }
    public boolean left = false, right = false, up = false, down = false, gotoTarget = false;
    Vector3f targetLocation = new Vector3f();
    Vector3f targetDirection = new Vector3f();
    // phisics variables
    private static final float DEFAULT_MASS = 1.5f;
    float airTime = 0;
    float runSpeed = 220;
    float walkSpeed = 130;

    public Character() {
        this(DEFAULT_MASS);
    }

    public Character(float mass) {
        super("character");
    }

    public Game getGame() {
        return game;
    }

    public void update(float tpf) {
        walkDirection.set(0, 0, 0);
        modelDirection.set(0, 0, 2);
        if (gotoTarget) {
            walkDirection.addLocal(targetDirection.normalizeLocal().clone().multLocal(0.2f));
            // verifica se chegou no destino "mouse target click"
            if (Math.abs(getLocalTranslation().x - targetLocation.x) < DISTANCE_STOP
                    && Math.abs(getLocalTranslation().z - targetLocation.z) < DISTANCE_STOP) {
                //if (getLocalTranslation().distance(targetLocation) < .5f) {
                    gotoTarget = false;
                //}
            }
        }
        if (!chControl.onGround()) {
            airTime = airTime + tpf;
        } else {
            airTime = 0;
        }
        if (walkDirection.length() == 0) {
            if (!"IdleTop".equals(animControl.getAnimationName()) && !"IdleBase".equals(animControl.getAnimationName())) {
                animControl.setStandAnim();
            }
        } else {
            modelRotation.lookAt(walkDirection, Vector3f.UNIT_Y);
            if (airTime > .3f) {
                if (!"IdleTop".equals(animControl.getAnimationName()) && !"IdleBase".equals(animControl.getAnimationName())) {
                    animControl.setStandAnim();
                }
            } else if (!"RunBase".equals(animControl.getAnimationName()) && !"RunTop".equals(animControl.getAnimationName())) {
                animControl.setWalkAnim();
            }
        }
        model.setLocalRotation(modelRotation);
        modelRotation.multLocal(modelDirection);
        modelRight.set(modelDirection);
        ROTATE_LEFT.multLocal(modelRight);
        chControl.setWalkDirection(walkDirection);
    }

    public void initCharacter(Game game) {
        this.game = game;
        //shadow
        setShadowMode(ShadowMode.CastAndReceive);
        // physics
        CapsuleCollisionShape capsule = new CapsuleCollisionShape(1.5f, 2f);
        chControl = new CharacterControl(capsule, 1.5f);
        addControl(chControl);
        game.getPhysicsSpace().add(chControl);
        //chControl.attachDebugShape(game.getAssetManager());
        initModel();
        initAnimations();
    }

    private void initModel() {
        model = (Node) game.getAssetManager().loadModel("Models/Sinbad/Sinbad.j3o");
        model.setLocalScale(0.5f);
        this.attachChild(model);
    }

    private void initAnimations() {
        animControl = new CharacterAnimControl(model.getControl(AnimControl.class));
        animControl.init();
    }

    public void setTargetLocation(Vector3f targetLocation) {
        this.targetLocation = targetLocation.clone();
        // cria um vetor de direção da posição atual para o alvo
        targetDirection = targetLocation.subtractLocal(getLocalTranslation());
        gotoTarget = true;
    }

    public CharacterControl getCharacterControl() {
        return chControl;
    }
}
